package org.skyui.beanmanagers;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Set;

import org.skyui.annotations.SkyManyToMany;
import org.skyui.annotations.SkyManyToOne;
import org.skyui.annotations.SkyOneToMany;
import org.skyui.beans.AbstractBean;
import org.skyui.config.BeansTableViewConfig;
import org.skyui.core.AccessControl;
import org.skyui.core.UIApplication;
import org.skyui.views.AbstractBeansTableView;
import org.skyui.views.AbstractBeansTableView.Action;

public class BeanRelationManager<B> extends AbstractBeanManager {

    /**
	 * 
	 */
    private static final long serialVersionUID = 5106701955023064556L;
    private AbstractBean parentBean;
    private Class globalManagerClass;
    private Field field;

    public BeanRelationManager(String field, AbstractBean parentBean) {

	super(null);
	if (parentBean.isTemplate()) {
	    return;
	}
	Field fd;
	try {
	    fd = parentBean.getClass().getDeclaredField(field);
	    fd.setAccessible(true);
	    this.field = fd;
	    this.beanClass = (Class) (((ParameterizedType) fd.getGenericType())
		    .getActualTypeArguments()[0]);
	} catch (SecurityException e) {
	    // TODO Auto-generated catch block
	    throw new Error(e);
	} catch (NoSuchFieldException e) {
	    // TODO Auto-generated catch block
	    throw new Error(e);
	}
	this.parentBean = parentBean;
	SkyManyToMany a1 = null;
	SkyManyToOne a2 = null;
	SkyOneToMany a3 = null;

	a1 = fd.getAnnotation(SkyManyToMany.class);
	if (a1 == null) {
	    a2 = fd.getAnnotation(SkyManyToOne.class);
	    if (a2 == null)
		a3 = fd.getAnnotation(SkyOneToMany.class);
	}

	String caption = null;
	String selectedCaption = null;
	String[] buttonNames = null;
	String addItemCaption = null;
	String[] roles = null;
	String[] productEditions = null;
	boolean show = false;
	if (a1 != null) {
	    caption = a1.caption();
	    selectedCaption = a1.selectedCaption();
	    buttonNames = a1.buttonNames();
	    addItemCaption = a1.addCaption();
	    show = a1.show();
	    roles = a1.roles();
	    productEditions = a1.productEditions();
	} else  if (a2 != null){
	    caption = a2.caption();
	    selectedCaption = a2.selectedCaption();
	    buttonNames = a2.buttonNames();
	    addItemCaption = a2.addCaption();
	    show = a2.show();
	    roles = a2.roles();
	    productEditions = a2.productEditions();
	} else if (a3 != null) {
	    caption = a3.caption();
	    selectedCaption = a3.selectedCaption();
	    buttonNames = a3.buttonNames();
	    addItemCaption = a3.addCaption();
	    show = a3.show();	
	    roles = a3.roles();
	    productEditions = a3.productEditions();
	}
	this.itemsCaption = caption;
	this.selectedItemCaption = selectedCaption;
	this.buttonNames = buttonNames;
	this.addItemCaption =  addItemCaption;
	this.isVisible = show
		&& AccessControl.isAccessible(roles, productEditions,
			UIApplication.getInstance());
	this.buttonActions = AbstractBeansTableView.DEFAULT_ACTIONS;
    }

    public final BeanSetManager getGlobalManager() {
	if (globalManagerClass == null)
	    this.globalManagerClass = beanClass;
	return BeanSetManager.getManager(this.globalManagerClass,
		getParentBean().getOrganization());
    }

    public Set<B> getCachedBeansSet() {
	try {
	    return (Set<B>) field.get(parentBean);
	} catch (IllegalArgumentException e) {
	    throw new Error(e);
	} catch (IllegalAccessException e) {
	    throw new Error(e);
	    // TODO Auto-generated catch block
	}
    }

    public AbstractBean getParentBean() {
	return this.parentBean;
    }

    protected String itemsCaption;
    protected String selectedItemCaption;
    protected String addItemCaption;
    protected String[] buttonNames;
    protected Action[] buttonActions;
    protected boolean isVisible;

    public String getItemsCaption() {
	return this.itemsCaption;
    }

    public String getSelectedItemCaption() {
	return this.selectedItemCaption;
    }

    public String getAddItemCaption() {
	return this.addItemCaption;
    }

    public String[] getButtonNames() {
	return this.buttonNames;
    }

    public Action[] getButtonActions() {
	return this.buttonActions;
    }

    public boolean isVisible() {
	return this.isVisible;
    }

}
